﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Mvc;
using System.Configuration;

using Microsoft.Practices.Unity;
using Microsoft.Practices.Unity.Configuration;

using ERPStore.Extensions;

namespace ERPStore.Web.IOC
{
    public class UnityContainerFactory
    {
        private System.Web.HttpContextBase m_Context;

		public UnityContainerFactory(System.Web.HttpContextBase ctx)
        {
            this.m_Context = ctx;
        }

        public Microsoft.Practices.Unity.IUnityContainer ConfiguredContainer(Microsoft.Practices.Unity.IUnityContainer container)
        {

            // overrides services mapping from config file
            LoadConfigurationOverrides(container);
			ConfigureMvcDependencyResolver(container);
			ConfigureWebApiDependencyResolver(container);
			ConfigureWorkflowDependencyResolver(container);

			return container;
        }

		private void ConfigureMvcDependencyResolver(IUnityContainer container)
		{
			var filterProvider = new UnityFilterProvider(container);
			container.RegisterInstance<IFilterProvider>("attributes", filterProvider);
			var resolver = new UnityDependencyResolver(container, System.Web.Mvc.DependencyResolver.Current);
			System.Web.Mvc.DependencyResolver.SetResolver(resolver);
		}


        private void LoadConfigurationOverrides(IUnityContainer container)
        {
            // Chargement des services et overriding a partir du fichier
            // de configuration unity.config
            var map = new ExeConfigurationFileMap();
            var unityConfigFileName = ERPStore.Configuration.ConfigurationSettings.AppSettings["unityConfigFileName"] ?? "unity.config";
			map.ExeConfigFilename = System.IO.Path.Combine(m_Context.Server.MapPath(@"\"), unityConfigFileName);
            var config = ConfigurationManager.OpenMappedExeConfiguration(map, ConfigurationUserLevel.None);
            var section = (UnityConfigurationSection)config.GetSection("unity");
            if (section == null)
            {
				return;
            }

			try
			{
				section.Configure(container);
			}
			catch(Exception ex)
			{
				var registrations = section.Containers[0].Registrations;
				// Check du mapping dans le fichier de config
				var fileNameList = registrations.Select(i => i.TypeName.Split(',')[1].Trim()).Distinct();
				foreach (var fileName in fileNameList)
				{
					var rootFolder = m_Context.Server.MapPath("/");
					var f = System.IO.Path.Combine(rootFolder, fileName + ".dll");
					if (System.IO.File.Exists(f))
					{
						continue;
					}
					f = System.IO.Path.Combine(rootFolder, "bin", fileName + ".dll");
					if (System.IO.File.Exists(f))
					{
						continue;
					}

					throw new System.IO.FileNotFoundException("File does not exists : " + f);
				}

				var message = string.Empty;
				foreach (var typeEntry in registrations)
				{
					Type fromType, toType;

					try
					{
						fromType = Type.GetType(typeEntry.TypeName, true);
						message = message + "FromType : " + typeEntry.TypeName + "\r\n";
					}
					catch
					{
						throw new Exception("Could not create the contract type: " + typeEntry.TypeName);
					}

					try
					{
						toType = Type.GetType(typeEntry.MapToName, true);
						message = message + "ToType : " + typeEntry.MapToName + "\r\n";
					}
					catch
					{
						throw new Exception("Could not create the mapped type: " + typeEntry.MapToName);
					}
				}

				throw new Exception("unity.config failed : " + message);
			}
        }

    }
}
